package com.cstp.manage;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cstp.entity.Question;
import com.cstp.entity.QuestionOption;
import com.cstp.exception.ServiceException;
import com.cstp.service.QuestionOptionService;
import com.cstp.service.QuestionService;
import com.cstp.web.req.QuestionOptionReq;
import com.cstp.web.req.QuestionPageReq;
import com.cstp.web.req.QuestionReq;
import lombok.SneakyThrows;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author watts
 */
@Component
@Transactional(rollbackFor = Exception.class)
public class QuestionManage {


    @Resource
    private QuestionService questionService;

    @Resource
    private QuestionOptionService optionService;

    @CacheEvict(value = "purchase", key = "'purchase-all'")
    @SneakyThrows
    public boolean publish(QuestionReq param) {
        //检查
        long answerCount = param.getOptions().stream().filter(qo -> qo.getIsAnswer() == 1).count();
        if (answerCount > 1 || answerCount == 0) {
            throw new ServiceException("至少/最多一个答案");
        }
        //保存问题
        Question question = Question.of(param);
        question.setType(param.getType());
        question.setModifyTime(LocalDateTime.now());
        questionService.saveOrUpdate(question);
        //删除多余问题
        if (question.getId() != null) {
            List<Long> dbIds = optionService.lambdaQuery()
                                            .eq(QuestionOption::getQuestionId, question.getId())
                                            .list()
                                            .stream()
                                            .map(QuestionOption::getId)
                                            .collect(Collectors.toList());
            List<Long> ids = param.getOptions().stream().map(QuestionOptionReq::getId).filter(Objects::nonNull).collect(Collectors.toList());
            dbIds.removeAll(ids);
            optionService.removeByIds(dbIds);
        }
        //保存选项
        optionService
                .saveOrUpdateBatch(param.getOptions()
                                        .stream()
                                        .map(QuestionOption::of)
                                        .peek(q -> q.setQuestionId(question.getId()))
                                        .collect(Collectors.toList()));
        return true;
    }

    @CacheEvict(value = "purchase", key = "'purchase-all'")
    public boolean delete(Long id) {
        optionService.lambdaUpdate()
                     .eq(QuestionOption::getQuestionId, id)
                     .remove();
        return questionService.removeById(id);
    }

    public Question detail(Long id) {
        Question question = questionService.getById(id);
        question.setOptions(optionService.lambdaQuery()
                                         .eq(QuestionOption::getQuestionId, id)
                                         .list());
        return question;
    }

    public IPage<Question> list(QuestionPageReq param) {
        return questionService.page(new Page<>(param.getPageNum(), param.getPageSize()), new QueryWrapper<Question>()
                .like(Objects.nonNull(param.getTitle()), "title", param.getTitle())
                .eq(Objects.nonNull(param.getType()), "type", param.getType()));

    }

    public List<Question> random5() {
        List<Question> all = questionService.all();
        Collections.shuffle(all);
        return all.stream()
                  .limit(5)
                  .peek(question ->
                          question.setOptions(optionService
                                  .lambdaQuery()
                                  .eq(QuestionOption::getQuestionId, question.getId())
                                  .list())
                  )
                  .collect(Collectors.toList());
    }
}
